﻿using System.Data.Common;
using System.Xml.Linq;
using PengSW.XmlTools;

namespace PengSW.DbTools
{
    public class GeneralDataSource
    {
        public GeneralDataSource()
        {
            DataProvider = "System.Data.SqlClient";
        }

        public GeneralDataSource(string aDataProvider, string aConnectionStringWithoutPassword, string aPassword)
        {
            DataProvider = aDataProvider;
            ConnectionStringWithoutPassword = aConnectionStringWithoutPassword;
            Password = aPassword;
        }
        private string m_DataProvider;
        public string DataProvider 
        {
            get { return m_DataProvider; }
            set
            {
                if (m_DataProvider == value) return;
                m_DbProviderFactory = null;
                m_DataProvider = value;
            }
        }

        private string m_ConnectionStringWithoutPassword;
        public string ConnectionStringWithoutPassword 
        { 
            get { return m_ConnectionStringWithoutPassword; }
            set { m_ConnectionStringWithoutPassword = value; }
        }

        public string Password { get; set; }

        public string ConnectionString
        {
            get
            {
                DbConnectionStringBuilder aConnectionStringBuilder = new DbConnectionStringBuilder(false)
                {
                    ConnectionString = ConnectionStringWithoutPassword
                };
                if (Password != string.Empty) aConnectionStringBuilder.Add("Password", Password);
                return aConnectionStringBuilder.ConnectionString;
            }
        }

        private DbProviderFactory m_DbProviderFactory = null;
        public DbProviderFactory DbProviderFactory 
        {
            get
            {
                if (m_DbProviderFactory == null) m_DbProviderFactory = DbProviderFactories.GetFactory(DataProvider);
                return m_DbProviderFactory;
            }
        }

        public bool IsValid
        {
            get
            {
                return !string.IsNullOrEmpty(DataProvider) && !string.IsNullOrEmpty(ConnectionStringWithoutPassword);
            }
        }

        public DbConnection CreateConnection()
        {
            DbConnection aConnection = DbProviderFactory.CreateConnection();
            aConnection.ConnectionString = ConnectionString;
            return aConnection;
        }

        public DbCommand CreateCommand(DbConnection aConnection, string aCommandText)
        {
            DbCommand aCommand = DbProviderFactory.CreateCommand();
            aCommand.Connection = aConnection;
            aCommand.CommandText = aCommandText;
            return aCommand;
        }

        public DbCommandBuilder CreateCommandBuilder()
        {
            DbCommandBuilder aCommandBuilder = DbProviderFactory.CreateCommandBuilder();
            return aCommandBuilder;
        }

        public DbDataAdapter CreateDataAdapter(DbConnection aConnection, string aSelectCommandText)
        {
            DbCommand aSelectCommand = CreateCommand(aConnection, aSelectCommandText);
            DbDataAdapter aDataAdapter = DbProviderFactory.CreateDataAdapter();
            aDataAdapter.SelectCommand = aSelectCommand;
            return aDataAdapter;
        }

        public void SetDataAdapterCommand(DbDataAdapter aDataAdapter, bool aUpdatable, bool aInsertable, bool aDeletable)
        {
            DbCommandBuilder aCommandBuilder = DbProviderFactory.CreateCommandBuilder();
            aCommandBuilder.DataAdapter = aDataAdapter;
            if (aUpdatable) aDataAdapter.UpdateCommand = aCommandBuilder.GetUpdateCommand();
            if (aInsertable) aDataAdapter.InsertCommand = aCommandBuilder.GetInsertCommand();
            if (aDeletable) aDataAdapter.DeleteCommand = aCommandBuilder.GetDeleteCommand();
        }

        public void ReadFromXElement(XElement aXElement)
        {
            if (aXElement == null) return;
            DataProvider = aXElement.GetChildNodeValue("DataProvider", DataProvider);
            ConnectionStringWithoutPassword = aXElement.GetChildNodeValue("ConnectionStringWithoutPassword", ConnectionStringWithoutPassword);
            Password = Crypt.Crypt.Decode(aXElement.GetChildNodeValue("Password", Crypt.Crypt.Encode(Password, KEY_64, IV_64)), KEY_64, IV_64);
        }

        public XElement CreateXElement(string aXElementName)
        {
            return new XElement(aXElementName,
                new XElement("DataProvider", DataProvider),
                new XElement("ConnectionStringWithoutPassword", ConnectionStringWithoutPassword),
                new XElement("Password", Crypt.Crypt.Encode(Password, KEY_64, IV_64)));
        }

        public GeneralDataSource Clone()
        {
            GeneralDataSource aCopy = new GeneralDataSource
            {
                DataProvider = DataProvider,
                ConnectionStringWithoutPassword = ConnectionStringWithoutPassword,
                Password = Password
            };
            return aCopy;
        }

        private const string KEY_64 = "GeneDaSo";
        private const string IV_64 = "DataGene";
    }
}
